package com.mdd.front.service.pay.impl;


import com.alibaba.fastjson2.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.mdd.common.config.AlipayConfig;
import com.mdd.common.entity.order.Order;
import com.mdd.common.entity.recharge.RechargeOrder;
import com.mdd.common.enums.OrderPayStatusEnum;
import com.mdd.common.enums.OrderStatusEnum;
import com.mdd.common.exception.OperateException;
import com.mdd.common.mapper.recharge.RechargeOrderMapper;
import com.mdd.common.utils.*;
import com.mdd.front.LikeFrontThreadLocal;
import com.mdd.front.service.pay.IBalancePayService;
import com.mdd.front.service.pay.IH5PayService;
import com.mdd.front.service.order.IOrderService;
import com.mdd.front.service.recharge.IRechargeService;
import com.mdd.front.validate.BalancePayValidate;
import com.mdd.front.vo.wxpay.WxPayCreateOrderRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import javax.validation.groups.Default;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Map;

/**
 * @author kn4im3
 * @date 2023/2/24 15:01
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class H5PayServiceImpl implements IH5PayService {
    @Resource
    private IOrderService iOrderService;
    @Resource
    private IRechargeService iRechargeService;
    @Resource
    private IBalancePayService iBalancePayService;
    @Resource
    private RechargeOrderMapper rechargeOrderMapper;
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
    @Value("${wx.pay.order-notify-url}")
    private String orderNotifyUrl;

    @Value("${ali.pay.order-notify-url}")
    private String aliPayNotifyUrl;

    @Value("${ali.pay.order-return-url}")
    private String aliPayReturnUrl;

    /**
     * @param request 请求数据
     * @return H5支付连接
     */
    @Override
    public String createH5Order(WxPayCreateOrderRequest request) throws WxPayException {
        // 订单编号
        String orderSn = "";
        // 订单状态
        Integer orderStatus = 0;
        // 订单金额
        BigDecimal orderAmount = BigDecimal.ZERO;

        switch (request.getScene()){
            case "order":
                Order order = this.iOrderService.getById(Long.valueOf(request.getOrderId()), LikeFrontThreadLocal.getUserId());
                orderSn = order.getSn();
                orderStatus = order.getOrderStatus();
                orderAmount = order.getOrderAmount();
                Assert.notNull(order, "订单不存在");
                break;
            case "recharge":
                RechargeOrder rechargeOrder = rechargeOrderMapper.selectOne(new QueryWrapper<RechargeOrder>()
                        .eq("id", request.getOrderId())
                        .eq("order_status", OrderStatusEnum.WAIT_PAY.getStatus())
                        .eq("pay_status", OrderPayStatusEnum.WAIT_PAY.getStatus())
                        .eq("user_id", LikeFrontThreadLocal.getUserId())
                        .last("limit 1"));
                orderSn = rechargeOrder.getOrderSn();
                orderStatus = rechargeOrder.getPayStatus();
                orderAmount = rechargeOrder.getOrderAmount();
                Assert.notNull(rechargeOrder, "订单不存在");
                break;
            default:
                throw new OperateException("不支持当前订单类型");
        }
        log.info("微信创建预支付订单请求对象:{}", request);
        Assert.isTrue(orderStatus != null && orderStatus == OrderStatusEnum.WAIT_PAY.getStatus(), "订单非待支付状态，不能创建支付单");
        String cancelUnpaidOrdersTimesStr = ConfigUtil.get("transaction", "cancel_unpaid_orders_times", "30");
        long cancelUnpaidOrdersTimes = Long.parseLong(cancelUnpaidOrdersTimesStr);
        Long expireTime = TimeUtil.timestamp() * 1000 + cancelUnpaidOrdersTimes * 60 * 1000;
        String timeExpire = format.format(expireTime) + "+08:00";
        WxPayService wxPayService = WxPayServiceUtils.wxPayService(request.getPayChannel());
        wxPayService.closeOrderV3(orderSn);
        if ("order".equals(request.getScene())){
            Order order = this.iOrderService.updateSn(request.getOrderId(), request.getPayChannel());
            orderSn = order.getSn();
        }
        if ("recharge".equals(request.getScene())){
            RechargeOrder rechargeOrder = iRechargeService.updateSn(request.getOrderId(), request.getPayChannel());
            orderSn = rechargeOrder.getOrderSn();
        }
        WxPayUnifiedOrderV3Request wxPayUnifiedOrderV3Request = new WxPayUnifiedOrderV3Request();
        wxPayUnifiedOrderV3Request.setOutTradeNo(orderSn);
        wxPayUnifiedOrderV3Request.setNotifyUrl(UrlUtil.localDomain(orderNotifyUrl));
        wxPayUnifiedOrderV3Request.setDescription("上门预约-支付订单");
        wxPayUnifiedOrderV3Request.setTimeExpire(timeExpire);
        wxPayUnifiedOrderV3Request.setSceneInfo(request.getSceneInfo());
        WxPayUnifiedOrderV3Request.Amount amount = new WxPayUnifiedOrderV3Request.Amount();
        amount.setTotal(AmountUtil.yuan2Fen(orderAmount.toPlainString()));
        amount.setCurrency("CNY");
        wxPayUnifiedOrderV3Request.setAmount(amount);
        log.info("微信创建预支付订单请求对象{}", wxPayUnifiedOrderV3Request);
        String h5Url = wxPayService.createOrderV3(TradeTypeEnum.H5, wxPayUnifiedOrderV3Request);
        log.info("微信创建预支付订单结果:{}", h5Url);
        return h5Url;
    }

    @Override
    public Object prePay(WxPayCreateOrderRequest request) throws WxPayException, AlipayApiException {
        // 更新支付方式
        switch (request.getScene()){
            case "order":
                iOrderService.updateOrderPayWay(request.getOrderId(), request.getPayWay());
                break;
            case "recharge":
                Map<String, String> config = ConfigUtil.get("recharge");
                String rechargeOpen = config.getOrDefault("rechargeOpen", "0");
                Assert.isTrue(0 != Integer.parseInt(rechargeOpen),"系统暂未开启充值功能哦!");
                iRechargeService.updateRechargePayWay(request.getOrderId(), request.getPayWay());
                break;
        }
        switch (request.getPayWay()){
            case 1:
                return this.createH5Order(request);
            case 2:
                Assert.isTrue(!"recharge".equals(request.getScene()),"充值订单不支持余额支付！");
                BalancePayValidate balancePayValidate = new BalancePayValidate();
                balancePayValidate.setOrderId(request.getOrderId());
                iBalancePayService.balance2PayOrder(balancePayValidate, LikeFrontThreadLocal.getUserId());
                return "支付成功！";
            case 3: //支付宝
                return this.createAliH5Order(request);
        }
        return "支付失败";
    }

    @Override
    public String createAliH5Order(WxPayCreateOrderRequest request) throws WxPayException, AlipayApiException {

        // 订单编号
        String orderSn = "";
        // 订单状态
        Integer orderStatus = 0;
        // 订单金额
        BigDecimal orderAmount = BigDecimal.ZERO;
        Long orderId = 0L;
        String payReturnUrl = "";
        switch (request.getScene()){
            case "order":
                Order order = this.iOrderService.getById(Long.valueOf(request.getOrderId()), LikeFrontThreadLocal.getUserId());
                orderSn = order.getSn();
                orderStatus = order.getOrderStatus();
                orderAmount = order.getOrderAmount();
                orderId = order.getId();
                payReturnUrl = UrlUtil.localDomain(aliPayReturnUrl) + "?order_id=" + orderId;
                Assert.notNull(order, "订单不存在");
                break;
            case "recharge":
                RechargeOrder rechargeOrder = rechargeOrderMapper.selectOne(new QueryWrapper<RechargeOrder>()
                        .eq("id", request.getOrderId())
                        .eq("order_status", OrderStatusEnum.WAIT_PAY.getStatus())
                        .eq("pay_status", OrderPayStatusEnum.WAIT_PAY.getStatus())
                        .eq("user_id", LikeFrontThreadLocal.getUserId())
                        .last("limit 1"));
                orderSn = rechargeOrder.getOrderSn();
                orderStatus = rechargeOrder.getPayStatus();
                orderAmount = rechargeOrder.getOrderAmount();
                orderId = Long.valueOf(rechargeOrder.getId());
                payReturnUrl = UrlUtil.localDomain(aliPayReturnUrl) + "?order_id=" + orderId + "&order_type=recharge";
                Assert.notNull(rechargeOrder, "订单不存在");
                break;
            default:
                throw new OperateException("不支持当前订单类型");
        }
        Assert.isTrue(orderStatus != null && orderStatus == OrderStatusEnum.WAIT_PAY.getStatus(), "订单非待支付状态,不能创建支付单");

        if ("order".equals(request.getScene())){
            Order order = this.iOrderService.updateSn(request.getOrderId(), request.getPayChannel());
            orderSn = order.getSn();
            //payReturnUrl = aliPayReturnUrl + "?order_id=" + orderId;
        }
        if ("recharge".equals(request.getScene())){
            RechargeOrder rechargeOrder = iRechargeService.updateSn(request.getOrderId(), request.getPayChannel());
            orderSn = rechargeOrder.getOrderSn();
        }
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.GATEWAY_URL, ConfigUtil.getAliDevPay("app_id"), ConfigUtil.getAliDevPay("private_key"), "json", AlipayConfig.CHARSET, ConfigUtil.getAliDevPay("ali_public_key"), AlipayConfig.SIGN_TYPE);
        //2、封装 Request
        AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();
        //alipayRequest.setNotifyUrl("http://z4cvwn.natappfree.cc" + aliPayNotifyUrl);
        alipayRequest.setNotifyUrl(UrlUtil.localDomain(aliPayNotifyUrl));
        alipayRequest.setReturnUrl(payReturnUrl);

        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", orderSn);
        bizContent.put("total_amount", orderAmount);
        bizContent.put("subject", "上门预约-支付订单");
        bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
        bizContent.put("app_pay", "Y");
        alipayRequest.setBizContent(bizContent.toString());

        String form = "";
        try {
            //System.out.println(alipayClient.execute(alipayRequest).getBody());
            form = alipayClient.pageExecute(alipayRequest).getBody();
            return form;
        } catch (Exception e) {
	        log.warn(e.toString());
            log.warn(bizContent.toString());
            throw new OperateException(e.getMessage());

        }
    }

}
